package me.yricky.mayu.ui

import androidx.compose.foundation.*
import androidx.compose.foundation.gestures.FlingBehavior
import androidx.compose.foundation.gestures.ScrollableDefaults
import androidx.compose.foundation.gestures.ScrollableState
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Icon
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Add
import androidx.compose.material.icons.rounded.Remove
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.BiasAlignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.pointer.*
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.center
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlin.experimental.and
import kotlin.experimental.or

/**
 * @author Yricky
 * @date 2022/4/18
 */

fun Modifier.pointerEvent(
    eventType: PointerEventType,
    pass: PointerEventPass = PointerEventPass.Main,
    onEvent: AwaitPointerEventScope.(event: PointerEvent) -> Unit
) = pointerInput(eventType, pass, onEvent) {
    awaitPointerEventScope {
        while (true) {
            val event = awaitPointerEvent(pass)
            if (event.type == eventType) {
                onEvent(event)
            }
        }
    }
}

fun Modifier.focusEnterExit(focusRequester:FocusRequester):Modifier = pointerEvent(PointerEventType.Enter){
    focusRequester.requestFocus()
}.pointerEvent(PointerEventType.Exit){
    focusRequester.freeFocus()
}.focusRequester(focusRequester).focusable()

@Composable
fun NumberSelector(
    modifier: Modifier = Modifier,
    value:Int,
    valueRange:IntRange,
    onValueChanged:(Int)->Unit
){
    Surface(
        modifier,
        shape = RoundedCornerShape(64.dp),
        elevation = 8.dp
    ) {
        Row(Modifier.size(144.dp,48.dp),verticalAlignment = Alignment.CenterVertically){
            Icon(Icons.Rounded.Remove,"",Modifier.size(48.dp).clickable {

                onValueChanged((value-1).coerceIn(valueRange))
            }.padding(8.dp))
            Box(Modifier.size(48.dp)){
                Text("${value.coerceIn(valueRange)}",Modifier.align(Alignment.Center), fontSize = 20.sp)
            }
            Icon(Icons.Rounded.Add,"",Modifier.size(48.dp).clickable {
                onValueChanged((value+1).coerceIn(valueRange))
            }.padding(8.dp))
        }
    }
}

@JvmInline
value class Location4(private val value:Byte){
    companion object{
        const val Left:Byte = 0x01
        const val Top:Byte = 0x02
        const val BFalse:Byte = 0x00

        fun relative(currentOffset: Offset, center: IntOffset):Location4 = Location4(
            currentOffset.x < center.x,
            currentOffset.y < center.y
        )
    }
    private fun l() = value and Left != BFalse
    private fun t() = value and Top != BFalse
    val alignment:Alignment get()= BiasAlignment(
        if(l()) -1f else 1f,
        if(t()) -1f else 1f
    )

    val offset: IntOffset get() = IntOffset(0,if(t()) 40 else -40)
}

fun Location4(left:Boolean,top:Boolean):Location4 = Location4(
    (if(left) Location4.Left else Location4.BFalse) or
            (if(top) Location4.Top else Location4.BFalse)
)

@Composable
fun Modifier.pointLocation4(useLocation:(Location4)->Unit) = pointerEvent(PointerEventType.Move){
    useLocation(Location4.relative(it.changes.lastOrNull()?.position ?: Offset.Zero,size.center))
}

@Composable
fun Modifier.horizontalSpacer() = fillMaxWidth().padding(0.dp,4.dp).height(1.dp).alpha(0.2f).background(MaterialTheme.colors.onBackground)

fun LazyListState.previousPageIndex() = (firstVisibleItemIndex - layoutInfo.visibleItemsInfo.size/2 - 1).coerceIn(0 until layoutInfo.totalItemsCount.coerceAtLeast(0))
fun LazyListState.nextPageIndex() = (firstVisibleItemIndex + layoutInfo.visibleItemsInfo.size/2 + 1).coerceIn(0 until layoutInfo.totalItemsCount.coerceAtLeast(0))